package com.iqiao.common.web;

import com.iqiao.common.util.date.ContextUtil;
import com.iqiao.common.util.json.JsonUtil;
import com.iqiao.common.web.result.JsonResult;
import com.iqiao.common.web.wrapper.FilterRequestWrapper;
import com.iqiao.common.web.wrapper.FilterResponseWrapper;
import com.iqiao.platform.model.UserOpLog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.*;

/**
 * 执行时间过滤器
 */
public class ProcessTimeFilter implements Filter {

	protected final Logger logger = LoggerFactory.getLogger(this.getClass());
	/**
	 * 请求执行开始时间
	 */
	public static final String START_TIME = "_start_time";

	public void destroy() {
	}

	public void doFilter(ServletRequest req, ServletResponse resp,
						 FilterChain chain) throws IOException, ServletException {

		FilterRequestWrapper requestWrapper = new FilterRequestWrapper((HttpServletRequest) req);  //替换
		FilterResponseWrapper responseWrapper = new FilterResponseWrapper((HttpServletResponse) resp);

		UserOpLog userOpLog = new UserOpLog();
		userOpLog.setCtime(new Date());
		userOpLog.setUserId(ContextUtil.getCurrentUserId());
		try {
			this.logRequest(userOpLog, requestWrapper);
		} catch (Exception e) {
			e.printStackTrace();
		}
		chain.doFilter(requestWrapper, responseWrapper);
		try {
			this.logRequestResponse(userOpLog, responseWrapper);
		} catch (Exception e) {
			e.printStackTrace();
		}

		userOpLog.setCostMs(System.currentTimeMillis() - userOpLog.getCtime().getTime());

		logger.debug("process in {} ms: {}", userOpLog.getCostMs(), requestWrapper.getRequestURI());
		logger.info("日志参数:{}", userOpLog.toString());
		resp.getOutputStream().write(responseWrapper.getTextContent().getBytes(resp.getCharacterEncoding()));
	}

	public void init(FilterConfig arg0) throws ServletException {
	}

	private void logRequest(UserOpLog userOpLog, FilterRequestWrapper request) throws IOException {
		// 请求参数日志信息
		Map<String, Object> params = new HashMap<>();
		String ip = Servlets.getIpAddress(request);

		userOpLog.setIp(ip);
		userOpLog.setUserAgent(request.getHeader("user-agent"));
		userOpLog.setMethod(request.getMethod());
		userOpLog.setUrl(request.getRequestURL().toString());

		//获取query string 或 posted form data参数
		Map<String, String[]> paramMap = request.getParameterMap();
		if (paramMap != null && paramMap.size() > 0) {
			params.put("query", JsonUtil.toJson(paramMap));
		}

		if(!"GET".equalsIgnoreCase(request.getMethod())){
			String body = this.getBodyString(request.getReader());
			params.put("body", JsonUtil.toObject(body, Object.class));
		}

		userOpLog.setParams(JsonUtil.toJson(params));
	}

	private void logRequestResponse(UserOpLog userOpLog, FilterResponseWrapper responseWrapper) throws IOException {

		String content = responseWrapper.getTextContent();
		if (JsonUtil.jsonVerify(content)) {
			userOpLog.setStatus(responseWrapper.getStatus());
			JsonResult result = JsonUtil.toObject(content, JsonResult.class);
			if (result != null) {
				userOpLog.setResultCode(result.getCode());
				userOpLog.setResultMsg(result.getMessage());
			}
			userOpLog.setResult(JsonUtil.convert(content, Object.class));
		} else {
			userOpLog.setResult(content);
		}
	}

	private String getBodyString(BufferedReader br) {
		String inputLine;
		StringBuilder str = new StringBuilder();
		try {
			while ((inputLine = br.readLine()) != null) {
				str.append(inputLine);
			}
			br.close();
		} catch (IOException e) {
			System.out.println("IOException: " + e);
		}
		return str.toString();
	}
}
